package com.papper.mng.exception;

import com.papper.common.enums.ResultEnum;
import com.papper.common.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author:LaJiao
 * @date 2022年03月24日
 * @time 13时27
 * @Description:
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 处理自定义的业务异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = ServiceException.class)
    public ModelAndView bizExceptionHandler(HttpServletRequest req, ServiceException e, HandlerMethod handler) {
        logger.error("发生业务异常！原因是:[{}]-[{}]", e.getCode(), e.getError());
        if (isReturnJson(handler)) {
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("statusCode", ResultEnum.FAIL.getCode());
            modelAndView.addObject("message", e.getMessage());
            return modelAndView;
        } else {
            ModelAndView modelAndView = new ModelAndView("/error/error");
            modelAndView.addObject("message", e.getMessage());
            return modelAndView;
        }
    }

    /**
     * 数据校验异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = IllegalArgumentException.class)
    public ModelAndView IllegalArgumentException(HttpServletRequest req, IllegalArgumentException e, HandlerMethod handler) {
        logger.error("数据校验异常！原因是:[{}]", e.getMessage());
        if (isReturnJson(handler)) {
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("statusCode", ResultEnum.FAIL.getCode());
            modelAndView.addObject("message", e.getMessage());
            return modelAndView;
        } else {
            ModelAndView modelAndView = new ModelAndView("/error/error");
            modelAndView.addObject("message", e.getMessage());
            return modelAndView;
        }
    }

    /**
     * 处理空指针的异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView exceptionHandler(HttpServletRequest req, NullPointerException e, HandlerMethod handler) {
        logger.error("发生空指针异常！原因是:[{}]", e);
        if (isReturnJson(handler)) {
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("statusCode", ResultEnum.FAIL.getCode());
            modelAndView.addObject("message", e.getMessage());
            return modelAndView;
        } else {
            ModelAndView modelAndView = new ModelAndView("/error/error");
            modelAndView.addObject("message", e.getMessage());
            return modelAndView;
        }
    }

    /**
     * 处理其他异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public ModelAndView exceptionHandler(HttpServletRequest req, Exception e, HandlerMethod handler) {
        logger.error("发生异常！原因是:[{}]", e);
        if (isReturnJson(handler)) {
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject("statusCode", ResultEnum.FAIL.getCode());
            modelAndView.addObject("message", e.getMessage());
            return modelAndView;
        } else {
            ModelAndView modelAndView = new ModelAndView("/error/error");
            modelAndView.addObject("message", e.getMessage());
            return modelAndView;
        }
    }

    private boolean isReturnJson(HandlerMethod handler) {
        if (handler.getBeanType().isAnnotationPresent(RestController.class)) {
            return true;
        }
        Method method = handler.getMethod();
        return method.isAnnotationPresent(ResponseBody.class);
    }
}
